/* ipRouteLib.h - definitions for the route interface library */

/*
 * Copyright (c) 1984-2005 Wind River Systems, Inc.
 *
 * The right to copy, distribute, modify or otherwise make use
 * of this software may be licensed only pursuant to the terms
 * of an applicable Wind River license agreement.
 */

/*
modification history
--------------------
02b,10may05,niq  Changes to handle trimmed netmask
02a,24feb05,spm  removed unneeded route format values and macros (SPR #100995)
01z,24feb05,spm  performance updates and code cleanup (SPR #100995)
01y,28sep04,niq  Fix netmask reported in routing socket messages: SPR 102094
01x,17sep04,niq  Scale out routing sockets
01w,23aug04,rp   merged from COMP_WN_IPV6_BASE6_ITER5_TO_UNIFIED_PRE_MERGE
01v,09jun04,spm  removed duplicate include file for virtual stacks
01u,28may04,niq  Merging from base6 label POST_ITER5_FRZ16_REBASE
01t,24mar04,rp   include vsLib.h
01s,06dec03,niq  Move primary route indication from RTM flags to route flags
01r,20nov03,niq  osdep.h cleanup
01q,10nov03,cdw  Rebase from base6 iteration 1 view
01p,04nov03,rlm  Ran batch header path update for header re-org.
01o,23oct03,rlm  updated #includes for header re-org
01n,12mar03,niq  Export some utility functions for use by Fastpath
01m,28jan03,niq  Undo the previous change
01l,27jan03,niq  Remove the incorrect check for RTF_LOCAL when checking for
                 interface route
01k,21jan03,niq  Change the type of routeTos from ULONG to long
01j,17jan03,niq  Don't allocate rentry for rt_gwroute
01i,08jan03,niq  Return NULL genmsk for ARP entries
01h,19dec02,niq  Changes for genmask support
01g,22nov02,niq  Add support for Proxy ARP
01f,21nov02,niq  Add a macro
01e,12nov02,niq  Fix definition for interface route
01d,08nov02,niq  Add a new error code
01c,29oct02,niq  Eliminate the weight feature for host stack
01c,23oct02,spm  fixed name for virtual stack registration number
01b,15oct02,niq  Add some more prototypes
01a,02oct02,niq  file creation
*/

/*
DESCRIPTION
This file includes function prototypes for the routing interface, as well
as the route entry structures.
*/

#ifndef _INCipRouteLibh
#define _INCipRouteLibh

#ifdef __cplusplus
extern "C" {
#endif

#include <net/mbuf.h>
#include <sys/socket.h>          /* needed for route.h */
#include <netinet/in.h>    /* RT_PROTO_SET and RT_PROTO_GET */

#include <vwModNum.h>

#ifdef VIRTUAL_STACK
#include <netinet/vsLib.h>
#endif /* VIRTUAL_STACK */

/* errnos */

#define S_ipRouteLib_INVALID_STATE		(M_ipRouteLib | 1)
#define S_ipRouteLib_INVALID_PARAMS		(M_ipRouteLib | 2)
#define S_ipRouteLib_BAD_GATEWAY			(M_ipRouteLib | 3)

#define MAX_ROUTE_PROTO	20

/* routeTag values  understood by routing protocols */
#define RFC1745_DEFAULT_ROUTE_TAG 	0x0000	/* manual/default route */
#define RFC1745_CONF_EXTERNAL_ROUTE_TAG	0x8000	/* configured external routes 
						 * IP static to OSPF and BGP 
						 */
#define RFC1745_EGP_ORIGEGP_ROUTE_TAG	0x9000	/* BGP routes reached via OSPF
						 */
#define RFC1745_STUB_ASBR_BGP_ROUTE_TAG	0xa000	/* BGP routes at ASBR to STUB
						 * AS 
						 */
#define RFC1745_IGP_TO_OSPF_ROUTE_TAG	0xc000	/* IGP dynamic routes */
#define RFC1745_EGP_ORIGIGP_ROUTE_TAG_PER_AS 0xd000 /* BGP routes with orig IGP,
						    * next hop AS 
						    */
#define RFC1745_BGP_TO_OSPF_ROUTE_TAG 	0xe000	/* BGP origin */

/* Definitions for route usage. A routing table can exist for each usage type*/
#define ROUTE_USAGE_IPV4		0
#define ROUTE_USAGE_IPV6		1

#ifdef INET6
#define ROUTE_USAGES_MAX		ROUTE_USAGE_IPV6
#else
#define ROUTE_USAGES_MAX		ROUTE_USAGE_IPV4
#endif /* INET6 */

#define ROUTE_USAGE_IS_INVALID(x)	((ULONG)x > ROUTE_USAGES_MAX)

/* 
 * Definitions for the routeFormat field. The higher 16 bits represent
 * the route usage and the lower 16 bits the actual format
 */

/* Definitions for route source. Used in the ipRouteCreate  call */
#define ROUTE_MIB       0    /* metrics only in pRouteData */
#define ROUTE_KERNEL    1    /* static routes: additional data is NULL */
                             /* cloned routes: metrics and parent route */
#define ROUTE_SOCKET    2    /* route sockets: metrics and genmask */

#define RS_MAX		2
#define RS_IS_INVALID(x)	((ULONG)x > RS_MAX)
#define RT_REDIRECT_SRC	1	/* Used only for ipRouteModify */

/* Configuration parameters for the route library */
struct ipRouteConfigParams 
    {
    CFG_DATA_HDR       		  cfgh;
    u_char			  routeDefaultWeight;/* Default route weight */
    };
typedef struct ipRouteConfigParams	IP_ROUTE_CONFIG_PARAMS_T;

/* Definition for the route usage structure */
typedef struct ipRouteUsage
    {
    ULONG			routeUsage;	/* IPv4, IPv6 etc. */
    struct ipRouteDispatchTable *pRibDispTbl;	/* Pointer to dispatch table */
    void *			pRibCookie;	/* RIB cookie */
    long				numRoutes;	/* Number of routes */

#ifdef FINEGRAIN_LOCKING_MODEL
    ULONG			rdLockTid;	/* Owner of Rd lock */
    ULONG			walkLockTid;	/* Owner of Walk lock */

#ifdef DEBUG
    int				rdlockCnt;
    int				walklockCnt;
    int				wrlockCnt;
    char				rdlockBuf[80];
    char				rdunlockBuf[80];
    char				walklockBuf[80];
    char				walkunlockBuf[80];
    char				wrlockBuf[80];
    char				wrunlockBuf[80];
#endif

#endif /* FINEGRAIN_LOCKING_MODEL */

    } IP_ROUTE_USAGE_T;
typedef IP_ROUTE_USAGE_T *	IP_ROUTE_USAGE_ID;


/* Values for rtmFlags field of the struct rtentry structure */
#define ROUTE_PROXY_ARP		0x01

/*
 * The following macros are used to access fields within the rtentry
 * structure. Using macros to access fields allows the freedom to rename
 * or rearrange fields (across any sub-structures)
 */
#define ROUTE_GATEWAY(x)		((x)->rt_gateway)
#define ROUTE_AGE(x)		((x)->rt_mod)
#define ROUTE_PRIMARYFLAG(x)	((x)->rt_flags & RTF_PRIMARY)
#define CLR_ROUTE_PRIMARY_FLAG(x)	((x)->rt_flags &= ~RTF_PRIMARY)
#define SET_ROUTE_PRIMARY_FLAG(x)	((x)->rt_flags |= RTF_PRIMARY)
#define ROUTE_PROXY_ARP_FLAG(x)	((x)->rtmFlags & ROUTE_PROXY_ARP)
#define RREFCNT(x)		((x)->rt_refcnt)
#define RTM_FLAGS(x)		((x)->rtmFlags)
#define RFLAGS(x)			((x)->rt_flags)
#define ROUTE_IFA(x)		((x)->rt_ifa)
#define ROUTE_IFP(x)		((x)->rt_ifp)
#define ROUTE_METRICS(x)		((x)->rt_rmx)
#define ROUTE_PARENT(x)		((x)->rt_parent)
#define ROUTE_GWROUTE(x)		((x)->rt_gwroute)
#define ROUTE_GENMASK(x)		((x)->rt_genmask)
#define ROUTE_OUTPUT(x)		((x)->rt_output)

#ifdef ROUTER_STACK
#define ROUTE_WEIGHT(x)		((x)->rt_rmx.weight)
#else
#define ROUTE_WEIGHT(x) 		0
#endif  /* ROUTER_STACK */

#define ROUTE_TOS(x)		((x)->routeTos)
#define ROUTE_OWNER(x)		((x)->routeOwner)

#define ROUTE_PROTO(x)		ROUTE_OWNER(x)

/*
 * Macro for freeing the route entry. It checks if there is more than one
 * active reference. If so, the reference count is decremented. If there
 * are <= 1 active references, the entry is freed. The reference count
 * on a newly created entry is zero. If anyone retrieves the entry,
 * the reference count is bumped up. Note that the reference count
 * is not expected to be negative. We catch that in the ipRouteFree
 * routine. This routine is meant to be called only on entries that
 * are (or were) in the route table. Also the caller is expected to hold
 * the appropriate locks.
 */

#define _RTFREE(x)	\
	  do \
	       { \
	       if (RREFCNT (x) <= 1) \
		   ipRouteFree (x, TRUE); \
	       else \
	           --(RREFCNT (x)); \
	       } while (0)

/* Structure for specifying new metrics in the ipRouteModify call */
struct changeMetrics
    {
    BOOL		setMetrics;	/* update metrics too or just update */
      					/* the locks */
    u_long		cm_inits;	/* which metrics are we changing */
    struct rt_metrics	cm_rmx; 	/* metrics themselves */
    };

#define ARP_ROUTE(pRoute) \
	  ((pRoute)->rt_gateway->sa_family == AF_LINK && \
	   (RFLAGS ((pRoute)) & RTF_LLINFO))

/*
 * This macro is used to detect routes that had their gateway changed to
 * an ARP template by the internal route processing. The RTF_LOCAL is used
 * to detect loopback IPv6 routes which are added with a RTF_LINFO flag
 */

#define INTERFACE_ROUTE(pRoute) \
	  ((pRoute)->rt_gateway->sa_family == AF_LINK && \
	   (!(RFLAGS ((pRoute)) & RTF_LLINFO) || \
	    (RFLAGS ((pRoute)) & RTF_LOCAL)))

#define GET_INTERFACE_ADDR(pRoute)	((ROUTE_IFA (pRoute))->ifa_addr)

/* These macros return the protocol address for the given sockaddr */
#define SOCKADDR_IN(s) 	(((struct sockaddr_in *)(s))->sin_addr.s_addr)
#define IP4ADDR(pAddr)	((ULONG *) &(SOCKADDR_IN(pAddr)))

#ifdef INET6
#define SOCKADDR_IN6(s) 	(((struct sockaddr_in6 *)(s))->sin6_addr)
#define SA6(s) 		(((struct sockaddr_in6 *)(s))->sin6_addr)
#define IP6ADDR(pAddr)	((ULONG *) &(SOCKADDR_IN6(pAddr)))	

/* This macro checks if the given IPv6 addr is all zeros */

#define IP6_ADDR_IS_ZERO(s) (SA6(s).s6_addr32[0] == 0 && \
                             SA6(s).s6_addr32[1] == 0 && \
                             SA6(s).s6_addr32[2] == 0 && \
                             SA6(s).s6_addr32[3] == 0)
#define IPADDR_IS_ZERO(s) \
  ((s)->sa_family == AF_INET ? \
   ((s)->sa_len <= (u_char)IP4ADDR (0) || SOCKADDR_IN (s) == 0) :	\
   ((s)->sa_len <= (u_char)IP6ADDR (0) || IP6_ADDR_IS_ZERO (s)))  
		    
/* This macro checks if the given IPv6 addr is all ones */

#define IP6_ADDR_IS_ALLONES(s) (SA6(s).s6_addr32[0] == 0xffffffff && \
                             SA6(s).s6_addr32[1] == 0xffffffff && \
                             SA6(s).s6_addr32[2] == 0xffffffff && \
                             SA6(s).s6_addr32[3] == 0xffffffff)
#define IPADDR_IS_ALLONES(s) \
	((s)->sa_family == AF_INET ? SOCKADDR_IN (s) == 0xffffffff : \
	 IP6_ADDR_IS_ALLONES (s))
#else /* INET6 */

#define IPADDR_IS_ZERO(s) \
   ((s)->sa_len <= (u_char)IP4ADDR (0) || SOCKADDR_IN (s) == 0)
#define IPADDR_IS_ALLONES(s) (SOCKADDR_IN (s) == 0xffffffff)


#endif /* INET6 */

#ifdef DEBUG_CHECKS
#ifdef INET6
/*
 * The following macro returns a pointer to the start of the IP address
 * given the sockaddr structure. For unrecognized address families
 * it calls panic
 */
#define IPADDR(pAddr) (pAddr->sa_family == AF_INET ? IP4ADDR (pAddr) :\
                       (pAddr->sa_family == AF_INET6 ? IP6ADDR (pAddr) : \
                        (ULONG *) (panic("BAD address family: %d %x @ %s:%d\n", \
                                         pAddr->sa_family, pAddr, \
                                         __FILE__, __LINE__),\
                                   NULL)))

#else /* INET6 */
/*
 * The following macro returns a pointer to the start of the IP address
 * given the sockaddr structure. For unrecognized address families
 * it calls panic
 */

#define IPADDR(pAddr) (pAddr->sa_family == AF_INET ? IP4ADDR (pAddr) : \
                       (ULONG *) (panic ("BAD address family: %d %x @ %s:%d\n", \
                                         pAddr->sa_family, pAddr, \
					 __FILE__, __LINE__), \
                                  NULL))

#endif /* INET6 */
#else /* DEBUG_CHECKS */
#ifdef INET6
/*
 * The following macro returns a pointer to the start of the IPv4 or IPv6
 * address within a sockaddr structure. It silently ignores unrecognized
 * address families, since debugging is not enabled.
 */
#define IPADDR(pAddr) ((pAddr)->sa_family == AF_INET ? \
                       (ULONG *) &(SOCKADDR_IN((pAddr))) : \
                        (ULONG *) &(SOCKADDR_IN6((pAddr))))

#else /* INET6 */
/*
 * The following macro returns a pointer to the start of the IPv4 address
 * within a sockaddr structure. It silently ignores unrecognized address
 * families, since debugging is not enabled.
 */

#define IPADDR(pAddr) ((ULONG *) &(SOCKADDR_IN((pAddr))))

#endif /* INET6 */ 
#endif /* DEBUG_CHECKS */

/* external function declarations */
#ifdef VIRTUAL_STACK
extern VS_REG_ID ipRouteRegistrationNum;
#endif /* VIRTUAL_STACK */
extern IP_ROUTE_CONFIG_PARAMS_T ipRouteDefaultConfigParams;

struct ipRouteDispatchTable;

/* Administrative functions */
STATUS ipRouteLibInit __P ((void));
STATUS ipRouteLibInstInit __P ((void *pRouteConfigParams));
STATUS ipRouteLibShutdown __P (());
#ifdef VIRTUAL_STACK
STATUS ipRouteLibDestructor __P ((VSNUM vsnum));
#endif /* VIRTUAL_STACK */
STATUS ipRouteTableSet __P ((ULONG routeUsage, 
			     struct ipRouteDispatchTable * pRibOps));
STATUS ipRouteTableCreate __P ((ULONG routeUsage));
STATUS ipRouteTablesCreate __P ((void));
STATUS ipRouteTableDestroy __P ((ULONG routeUsage));
STATUS ipRouteTableShow __P ((int routeUsage));

/* Core functions - Route creation, deletion, modification, retrieval, free */
STATUS ipRouteCreate __P ((struct sockaddr * pDstAddr, 
			   struct sockaddr * pNetmask, 
			   struct sockaddr * pGateway, ULONG routeIndex, 
			   ULONG routeTos, ULONG routeOwner, ULONG routeSource,
			   ULONG routeFormat, UCHAR routeWeight, 
			   ULONG routeFlags, void * pRouteData, 
			   void * pCustomData, struct rtentry **ppRtEntry));
STATUS ipRouteDelete __P ((struct sockaddr * pDstAddr, 
			   struct sockaddr * pNetmask, 
			   struct sockaddr * pGateway, long routeTos, 
			   ULONG routeOwner, ULONG routeFormat));
STATUS ipIntRouteDelete __P ((struct sockaddr * pDstAddr, 
			      struct sockaddr * pNetmask, 
			      struct sockaddr * pGateway, long routeTos, 
			      ULONG routeOwner, ULONG routeFormat,
			      struct rt_msghdr *pRtm));
struct rtentry * ipRouteGet __P ((struct sockaddr * pDstAddr, 
				struct sockaddr * pGateway, long routeTos, 
				ULONG routeOwner, ULONG routeFormat, 
				BOOL skipFlag));
struct rtentry * ipRouteLookup __P ((struct sockaddr * pDstAddr, 
				   struct sockaddr * pNetmask, 
				   struct sockaddr * pGateway, long routeTos, 
				   ULONG routeOwner, ULONG routeFormat));
struct rtentry * ipRouteLexGet __P ((struct sockaddr * pDstAddr, 
				   struct sockaddr * pNetmask, 
				   struct sockaddr * pGateway, ULONG routeTos, 
				   ULONG indexType, ULONG routeFormat));
struct rtentry * ipRouteLexNextGet __P ((struct sockaddr * pDstAddr, 
				       struct sockaddr * pNetmask, 
				       struct sockaddr * pGateway, 
				       ULONG * pTos, ULONG indexType, 
				       ULONG routeFormat));
STATUS ipRouteModify __P ((struct sockaddr * pDstAddr, 
			   struct sockaddr * pNetmask, 
			   struct sockaddr * pGateway, ULONG routeIndex, 
			   long routeTos, ULONG routeOwner, ULONG routeSource,
			   ULONG routeFormat, struct sockaddr * pNewGateway, 
			   UCHAR * pNewWeight, ULONG * pNewFlags, 
			   void * pNewRouteData, void * pNewCustomData));
STATUS ipIntRouteModify __P ((struct sockaddr * pDstAddr, 
			      struct sockaddr * pNetmask, 
			      struct sockaddr * pGateway, ULONG routeIndex, 
			      long routeTos, ULONG routeOwner, 
			      ULONG routeSource, ULONG routeFormat, 
			      struct sockaddr * pNewGateway, 
			      UCHAR * pNewWeight, ULONG * pNewFlags, 
			      void * pNewRouteData, void * pNewCustomData,
			      struct rt_msghdr *pRtm));
void ipRouteUnlock __P ((struct rtentry * pRoute));
void ipRouteLock __P ((struct rtentry * pRoute));
void ipRouteUnlockOrDelete __P ((struct rtentry * pRoute));
STATUS ipRouteNumRoutesGet __P ((int routeUsage));

/* Support functions - needed by other parts of the code */
STATUS ipRouteTableWalk __P ((ULONG routeUsage, 
			      void (* pFunc )(struct rtentry * rt, void * pArg),
			      void * pArg));
struct rtentry * ipRouteMatch __P ((struct rtentry * pRoute, 
				  struct sockaddr * pGateway, long routeTos,
				  ULONG routeOwner));
int rt_setgate __P ((struct rtentry *rt, struct sockaddr * pDstAddr, 
		     struct sockaddr * pGate));
void ipRouteNetmaskTrim (int routeFormat, struct sockaddr * pNetmask);
#ifdef __cplusplus
}
#endif

#endif /* _INCrouteEnhLibh */
